POJ_3061

题意

给一个数字串,一个S,求最短连续串之和大于S的长度

思路

solve_1
用的是尺取法。比如[s,t]是一个合法状态,必有[s+1 , t’],t’>t.此时可以使用尺取法。
solve_2
用的是双指针发。

AC代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
#include <iostream>
#include <algorithm>
#include <cmath>
#include <cstdio>
#include <cstring>
#include <map>
using namespace std;
#define NV 100005
#define ll long long
ll sum[100005],s,a[100005];
int n,t,tmp;
//尺取法,复杂度 O(n*logn)
int solve_1(){
int ret=1e8;
for(int i = 1 ; sum[i]+s <= sum[n] ; i++){
int j = lower_bound(sum+i ,sum+1+n , sum[i]+s) - sum;
ret = min(ret , j -i);
}
return ret;
}
//双指针,复杂度 O(n)
int solve_2(){
int ret=1e8,i=0,j=0;
ll sums=0;
while(j<n){
while(sums<=s && j<n)sums+=a[++j];
while(sums>=s && i<n)sums-=a[++i];
ret = min(ret , j-i+1);
}
return ret;
}
int main(){
for(cin>>t;t--;){
cin>>n>>s;sum[0]=0;
for(int i=1 ; i<=n ;i++){
scanf("%d",&tmp);
sum[i]=sum[i-1]+tmp;
a[i]=tmp;
}
if(sum[n]<s)puts("0");
else{
/*printf("%d\n",solve_1());*/
printf("%d\n",solve_2());
}
}
return 0;
}